home *** CD-ROM | disk | FTP | other *** search
- ;* GUSDAC.ASM
- ;*
- ;* Gravis UltraSound Mixing Sound Device
- ;*
- ;* $Id: gusdac.asm,v 1.3 1997/01/16 18:41:59 pekangas Exp $
- ;*
- ;* Copyright 1996,1997 Housemarque Inc.
- ;*
- ;* This file is part of the MIDAS Sound System, and may only be
- ;* used, modified and distributed under the terms of the MIDAS
- ;* Sound System license, LICENSE.TXT. By continuing to use,
- ;* modify or distribute this file you indicate that you have
- ;* read the license and understand and accept it fully.
- ;*
-
-
-
- IDEAL
- P386
- JUMPS
-
- INCLUDE "lang.inc"
- INCLUDE "errors.inc"
- INCLUDE "sdevice.inc"
- INCLUDE "mixsd.inc"
- INCLUDE "dsm.inc"
- INCLUDE "dma.inc"
- INCLUDE "mutils.inc"
-
- ;BORDERS = 1
-
- GLOBAL LANG dmaBufferSize : _int
- GLOBAL LANG dmaPos : _int
- GLOBAL LANG mixPos : _int
- GLOBAL LANG buffer : dmaBuffer
- GLOBAL LANG buffer2 : dmaBuffer
- GLOBAL LANG uploaded : _int
-
-
- ;/***************************************************************************\
- ;* enum gdcFunctIDs
- ;* ----------------
- ;* Description: ID numbers for GUS DAC Sound Device functions
- ;\***************************************************************************/
-
- enum gdcFunctIDs \
- ID_gdcDetect = ID_gdc, \
- ID_gdcInit, \
- ID_gdcClose, \
- ID_gdcStartPlay
-
-
-
- DATASEG
-
- IFDEF __PASCAL__
- EXTRN GDC : SoundDevice
- ENDIF
-
-
- D_int selreg
- D_int voicesel
- D_int datalow
- D_int gdcRate
- D_int gdcMode
- D_int numChans
- D_int bufHalf
- D_int oldPos
- D_int uploaded
- D_int playing
- D_int dmaActive
- D_int gusDMAPos
-
-
- IDATASEG
-
-
- GDCCONFIGBITS = sdUsePort or sdUseDMA or sdUseMixRate or \
- sdUseOutputMode or sdUseDSM
- GDCMODEBITS = sdMono or sd8bit or sd16bit
-
- ; If compiling for Pascal, Sound Device name is gdcSD, from which the data
- ; will be copied to Sound Device GDC, defined in Pascal.
-
- IFDEF __PASCAL__
- SDNAM equ gdcSD
- ELSE
- SDNAM equ GDC
- ENDIF
-
- GLOBAL SDNAM : SoundDevice
-
- SDNAM SoundDevice < \
- 0,\
- GDCCONFIGBITS,\
- 220h, 0, 1,\
- 1, 1,\
- GDCMODEBITS,\
- ptr_to gdcSDName,\
- ptr_to gdcCardNames,\
- 6, ptr_to gdcPortAddresses,\
- ptr_to gdcDetect,\
- ptr_to gdcInit,\
- ptr_to gdcClose,\
- ptr_to dsmGetMixRate,\
- ptr_to mixsdGetMode,\
- ptr_to mixsdOpenChannels,\
- ptr_to dsmCloseChannels,\
- ptr_to dsmClearChannels,\
- ptr_to dsmMute,\
- ptr_to dsmPause,\
- ptr_to dsmSetMasterVolume,\
- ptr_to dsmGetMasterVolume,\
- ptr_to mixsdSetAmplification,\
- ptr_to mixsdGetAmplification,\
- ptr_to dsmPlaySound,\
- ptr_to dsmReleaseSound\
- ptr_to dsmStopSound,\
- ptr_to dsmSetRate,\
- ptr_to dsmGetRate,\
- ptr_to dsmSetVolume,\
- ptr_to dsmGetVolume,\
- ptr_to dsmSetSample,\
- ptr_to dsmGetSample,\
- ptr_to dsmSetPosition,\
- ptr_to dsmGetPosition,\
- ptr_to dsmGetDirection,\
- ptr_to dsmSetPanning,\
- ptr_to dsmGetPanning,\
- ptr_to dsmMuteChannel,\
- ptr_to dsmAddSample,\
- ptr_to dsmRemoveSample,\
- ptr_to mixsdSetUpdRate,\
- ptr_to gdcStartPlay,\
- ptr_to gdcPlay >
-
- gdcSDName DB "Gravis UltraSound Mixing Sound Device v0.05", 0
-
- gdcCardNames DD ptr_to gdcName
-
- gdcName DB "Gravis UltraSound Software Mixing", 0
-
- IFDEF __16__
- gdcPortAddresses DW 210h, 220h, 230h, 240h, 250h, 260h
- ELSE
- gdcPortAddresses DD 210h, 220h, 230h, 240h, 250h, 260h
- ENDIF
-
- env DB "ULTRASND",0
-
- chantab dw 44100,41160,38587,36317,34300,32494,30870,29400,28063,26843
- dw 25725,24696,23746,22866,22050,21289,20580,19916,19293
-
- buffer2 dmaBuffer ?
-
-
- CODESEG
-
- MACRO SetBorder color
- IFDEF BORDERS
- push _dx _ax
- mov dx,03DAh
- in al,dx
- mov dx,03C0h
- mov al,31h
- out dx,al
- mov al,color
- out dx,al
- pop _ax _dx
- ENDIF
- ENDM
-
- ;******* GUS Register Select - Macro ************
-
- MACRO regsel register
- mov _dx,[selreg]
- mov al,register
- out dx,al
- ENDM
-
- ;******* GUS-delay subroutine ************
-
- PROC gusdelay NEAR
- push _dx _ax
- mov dx,84h
- rept 8
- in al,dx
- endm
- pop _ax _dx
- ret
- ENDP
-
- ;/***************************************************************************\
- ;*
- ;* Function: gusReset
- ;*
- ;* Description: Resets the GUS card
- ;*
- ;* Destroys: al, dx
- ;*
- ;\***************************************************************************/
- PROC gusReset NEAR
-
- regsel 4ch ; RESET
- add _dx,2
- xor al,al
- out dx,al ; RESET!
-
- call gusdelay
- call gusdelay
-
- mov al,1
- out dx,al ; Enable GF1
-
- call gusdelay
- call gusdelay
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gdcDetect(int *result);
- ;*
- ;* Description: Detects Gravis UltraSound soundcard
- ;*
- ;* Returns: MIDAS error code.
- ;* 1 stored to *result if GUS was detected, 0 if not.
- ;*
- ;\***************************************************************************/
-
- PROC gdcDetect _funct result : _ptr
- USES _bx
-
- ; Search for "ULTRASND" environment string:
- IFDEF __16__
- call mGetEnv LANG, seg env offset env
- mov bx,dx ; was "ULTRASND" environment found?
- or bx,ax ; if not, no GUS
- jz @@noGUS
-
- mov es,dx ; point es:si to environment
- mov bx,ax ; string
-
- ELSE
- call mGetEnv LANG, offset env
- test eax,eax ; was "ULTRASND" environment found?
- jz @@noGUS ; if not, no GUS
-
- mov ebx,eax ; point _esbx to environment string
-
- ENDIF
- mov cl,3 ; 3 digits
- xor _ax,_ax
- @@dloop:
- mov dl,[_esbx]
- inc _bx
- sub dl,"0"
- shl _ax,4
- add al,dl
- dec cl
- jnz @@dloop
-
- mov [GDC.port],_ax
-
- ; Take Playback DMA-channel
- inc _bx
- xor _dx,_dx
- mov dl,[_esbx]
- sub dl,"0"
- mov [GDC.DMA],_dx
-
- ; Test if there really is a GUS
-
- add _ax,103h
- mov [selreg],_ax ; Register select (2x0h+103h)
-
- call gusReset
-
- regsel 44h
- add _dx,2
- xor al,al
- out dx,al ; upper bits of address
-
- regsel 43h
- inc _dx
- xor _ax,_ax ; Address 0
- out dx,ax
- add dx,3
- mov al,055h
- out dx,al ; Poke data 1 (55h)
-
- sub dx,3
- mov _ax,1 ; Address 1
- out dx,ax
- add dx,3
- mov al,0AAh
- out dx,al ; Poke data 2 (AAh)
-
- sub dx,3
- xor _ax,_ax ; Address 0
- out dx,ax
- add dx,3
- in al,dx ; Peek data 1
- cmp al,055h
- jne @@noGUS
-
- sub dx,3
- mov _ax,1 ; Address 1
- out dx,ax
- add dx,3
- in al,dx ; Peek data 2
- cmp al,0AAh
- je @@found
-
- @@noGUS:
- mov [GDC.port],0
- xor _ax,_ax ; No GUS found
- jmp @@quit
-
- @@found:
- mov _ax,1 ; GUS found
- @@quit:
- LOADPTR es,_bx,[result] ; store in *result
- mov [_int _esbx],_ax
- xor _ax,_ax
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gdcInit(unsigned mixRate, unsigned mode);
- ;*
- ;* Description: Initializes Gravis UltraSound
- ;*
- ;* Input: unsigned mixRate mixing rate
- ;* unsigned mode output mode (see enum sdMode)
- ;*
- ;* Returns: MIDAS error code
- ;*
- ;\***************************************************************************/
-
- PROC gdcInit _funct mixRate : _int, mode : _int
- USES _si,_di,_bx
-
- mov [gdcMode],0
-
- test [mode],sd8bit ; force 8-bit?
- jnz @@8b
- or [gdcMode],sd16bit ; if not, use 16 bits
- jmp @@bit
- @@8b: or [gdcMode],sd8bit
-
- @@bit:
- ; FIXME!!!
- or [gdcMode],sdMono
- mov _ax,[mixRate]
-
- mov [gdcRate],_ax
- mov [numChans],14 ; Always 14 channels active
- ; in mono mode
- mov [bufHalf],0
- mov [oldPos],0
- mov [playing],0
-
- mov _ax,[GDC.port] ; Base address (Set before!)
- add _ax,103h
- mov [selreg],_ax ; Register select (2x0h+103h)
- dec _ax
- mov [voicesel],_ax ; Voice select (2x0h+102h)
- add _ax,2
- mov [datalow],_ax ; Data Low Byte (2x0h+104h)
-
- call gusReset ; Reset GUS
-
-
- ; Clear all 32 channels
-
- mov _dx,[GDC.port] ; Mixer
- mov al,3
- out dx,al ; Disable Line in & out
-
- regsel 0eh
- add _dx,2
- mov al,31 OR 0c0h
- out dx,al ; Set number of active
- ; voices to 32 just for
- ; sure
-
- mov _cx,32 ; Number of voices
- @@resetloop:
- mov _dx,[voicesel] ; Voice Select
- mov _ax,_cx
- out dx,al
-
- regsel 0 ; Voice control
- add _dx,2 ; data low
- mov al,3 ; Stop voice
- out dx,al
-
- regsel 9 ; Current Volume
- inc _dx ; data high
- mov _ax,0500h ; Zero volume
- out dx,ax
-
- regsel 12 ; Pan Position
- add _dx,2 ; data low
- mov al,8 ; Center
- out dx,al
-
- regsel 13 ; Volume Ramping
- add _dx,2 ; data low
- mov al,3 ; disable
- out dx,al
-
- regsel 6 ; Ramp Rate
- add _dx,2
- mov al,3fh ; Rate
- out dx,al
-
- dec _cx
- jnz @@resetloop
-
- ; Take care of common initialization for all mixing Sound Devices:
- call mixsdInit LANG, [gdcRate], [gdcMode], -1
- test _ax,_ax
- jnz @@err
-
-
- ; Clear the GUS buffer
-
- regsel 4ch ; RESET
- add _dx,2
- mov al,3
- out dx,al ; Enable GF1 and DACs
-
- mov _cx,[dmaBufferSize]
- add _cx,32
-
- xor _bx,_bx
-
- regsel 44h ; Addr hi
- add _dx,2 ; 3x5
- xor _ax,_ax
- out dx,al ; upper bits of address
-
- regsel 43h ; Addr lo
- @@cloop:
- mov _dx,[datalow]
- mov _ax,_bx
- out dx,ax
- add _dx,3 ; 3x7
- xor al,al
- inc _bx
- out dx,al
- dec _cx
- jnz @@cloop
-
-
- ; Allocate an extra DMA buffer:
- mov _ax,[dmaBufferSize]
- call dmaAllocBuffer LANG, _ax, offset buffer2
- test _ax,_ax
- jnz @@err
-
- ; Set amount of open channels:
-
- regsel 0eh
- add _dx,2
- mov _ax,[numChans]
- dec _ax ; Amount-1
- or al,0c0h
- out dx,al
-
- mov _ax,[gdcRate]
- shl _ax,10
- xor _dx,_dx
- mov _bx,44100
- div _bx
- and _ax,NOT 1
-
- push _ax
-
- mov _dx,[voicesel] ; Select voice
- xor _ax,_ax
- out dx,al
-
- regsel 1 ; Frequency control
- inc _dx
- pop _ax
- out dx,ax
-
- mov _cx,[dmaBufferSize] ; Set sample end
- test [gdcMode],sd16bit
- jz @@bit8
- shr _cx,1
- @@bit8:
- dec _cx
- regsel 4 ; End position high
- inc _dx
- mov _ax,_cx
- shr _ax,7
- out dx,ax
- regsel 5 ; End position low
- inc _dx
- mov _ax,_cx
- shl _ax,9
- out dx,ax
-
- regsel 2 ; Start position high
- inc _dx
- xor _ax,_ax
- out dx,ax
- regsel 3 ; Start position low
- inc _dx
- xor _ax,_ax
- out dx,ax
-
- regsel 10 ; Current position high
- inc _dx
- xor _ax,_ax
- out dx,ax
- regsel 11 ; Current position low
- inc _dx
- xor _ax,_ax
- out dx,ax
-
- call gusdelay
-
- out dx,ax
-
- regsel 10 ; Current position high
- inc _dx
- xor _ax,_ax
- out dx,ax
-
- regsel 0 ; Voice control
- mov al,8 ; Loop
- test [gdcMode],sd16bit
- jz @@8bit
- or al,4 ; 16 bit
- @@8bit: add _dx,2
- out dx,al
- call gusdelay ; Delay
- out dx,al
-
- regsel 9 ; Current volume
- inc _dx
- mov ax,0ef00h
- out dx,ax
- call gusdelay
- out dx,ax
-
- call dmaStop LANG, [GDC.DMA]
-
- regsel 41h
- add _dx,2
- xor al,al
- out dx,al
-
- mov _dx,[GDC.port] ; Mixer
- xor al,al
- out dx,al ; Enable Line in & out
-
- @@ok: xor _ax,_ax ; gdc succesfully initialized
- jmp @@done
-
-
- @@err: ERROR ID_gdcInit
-
- @@done:
- ret
- ENDP
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gdcClose(void)
- ;*
- ;* Description: Uninitializes Gravis UltraSound
- ;*
- ;* Returns: MIDAS error code
- ;*
- ;\***************************************************************************/
-
- PROC gdcClose _funct
- USES _bx
-
- ; Stop DMA
- call dmaStop LANG, [GDC.DMA]
-
- regsel 41h
- add _dx,2
- xor al,al
- out dx,al
-
- call gusReset
-
- mov _dx,[GDC.port] ; Mixer
- xor al,al
- out dx,al ; Enable Line in & out
-
- ; Free the extra DMA buffer
- mov _ax,[dmaBufferSize]
- mov [buffer2.bufferLen],_ax
- call dmaFreeBuffer LANG, offset buffer2
- test _ax,_ax
- jnz @@err
-
- ; Take care of common uninitialization for all mixing Sound Devices:
- call mixsdClose
- test _ax,_ax
- jnz @@err
-
- xor _ax,_ax
- jmp @@done
-
-
- @@err: ERROR ID_gdcClose
-
- @@done:
- ret
- ENDP
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gdcStartPlay(void)
- ;*
- ;* Description: Update the "DMA"-position of GUS
- ;*
- ;* Returns: MIDAS error code
- ;*
- ;\***************************************************************************/
-
- PROC gdcStartPlay _funct
- USES _bx
-
- mov [dmaActive],0
-
- mov _dx,[voicesel] ; Select voice
- xor _ax,_ax
- out dx,al
-
- regsel 8ah ; Current position high
- inc _dx
- in ax,dx
-
- xor ecx,ecx
- mov _cx,_ax
- and _cx,01fffh
- shl ecx,7
-
- regsel 8bh ; Current position low
- inc _dx
- in ax,dx
- shr _ax,9
- or _cx,_ax
-
- test [gdcMode],sd16bit
- jz @@ok16
- add _cx,_cx
- @@ok16:
- mov _ax,_cx
- xor _dx,_dx
- idiv [dmaBufferSize]
- mov [dmaPos],_dx
-
- xor _ax,_ax
- ret
- ENDP
-
- ;/***************************************************************************\
- ;*
- ;* Function: int gdcPlay(int *play)
- ;*
- ;* Description: Uploads the mixing buffer contents to GUS
- ;*
- ;* Returns: MIDAS error code
- ;*
- ;\***************************************************************************/
-
- PROC gdcPlay _funct play:dword
- USES _si,_di,_bx
-
- call mixsdPlay LANG, [play]
-
- SetBorder(15)
-
- cmp [dmaActive],0
- jne @@skip
-
- cmp [playing],0
- je @@nodmacheck
-
- call dmaGetPos LANG, offset buffer2, offset gusDMAPos
- mov _si,[gusDMAPos]
- mov _di,8
-
- @@waitchange:
- call dmaGetPos LANG, offset buffer2, offset gusDMAPos
- cmp _si,[gusDMAPos]
- jne @@skip
- call gusdelay
- dec _di
- jnz @@waitchange
-
- ; regsel 41h
- ; add _dx,2
- ; in al,dx
- ; test al,40h
- ; jz @@skip
-
- @@nodmacheck:
- mov _cx,[mixPos]
- and _cx,NOT 31
- sub _cx,[oldPos]
- jns @@ok
-
- mov _cx,[dmaBufferSize]
- sub _cx,[oldPos]
- mov _bx,[oldPos]
- mov [oldPos],0
- test _cx,_cx
- jz @@skip
- jmp @@copy
-
- @@ok: cmp _cx,64
- jbe @@skip
-
- mov _bx,[oldPos]
- mov _ax,[mixPos]
- and _ax,NOT 31
- mov [oldPos],_ax
-
- @@copy:
- mov [buffer2.bufferLen],_cx
- mov [uploaded],_cx
- PUSHSEGREG ds
- LOADPTR ds,_si,[buffer.bufDataPtr]
- LOADPTR es,_di,[buffer2.bufDataPtr]
- add _si,_bx
- shr _cx,2
- cld
- rep movsd
- POPSEGREG ds
-
- push _bx
- call dmaStop LANG, [GDC.DMA]
-
- regsel 41h
- add _dx,2
- xor al,al
- out dx,al
- call gusdelay
- out dx,al
- pop _bx
-
- shr _bx,4
- cmp [GDC.DMA],4
- jb @@nope
- shr _bx,1
- @@nope:
- regsel 42h
- inc _dx
- mov _ax,_bx
- out dx,ax
-
- regsel 41h
- add _dx,2
-
- mov al,00000001b ; 650kb/s
- ; mov al,00001001b ; 325kb/s
- ; mov al,00010001b ; 217kb/s
- ; mov al,00011001b ; 163kb/s
- or al,20h
- cmp [GDC.DMA],4
- jb @@dmaok2
- or al,4 ; 16-bit DMA channel
- @@dmaok2:
- test [gdcMode],sd8bit
- jz @@oka2
- or al,80h ; Invert high bit
- @@oka2:
- ; And START!
- out dx,al
- call gusdelay
- out dx,al
-
- call dmaPlayBuffer LANG, offset buffer2, [GDC.DMA], 0
-
- regsel 41h
- add _dx,2
- in al,dx
-
- mov [playing],1
- mov [dmaActive],1
- @@skip:
- SetBorder(0)
- xor _ax,_ax
- ret
- ENDP
-
-
- ;* $Log: gusdac.asm,v $
- ;* Revision 1.3 1997/01/16 18:41:59 pekangas
- ;* Changed copyright messages to Housemarque
- ;*
- ;* Revision 1.2 1996/08/04 11:29:00 pekangas
- ;* All functions now preserve _Bx
- ;*
- ;* Revision 1.1 1996/05/22 20:49:33 pekangas
- ;* Initial revision
- ;*
-
- END